/* ** por compatibilidad se omiten tildes **
================================================================================
 TRABAJO PRACTICO 3 - System Programming - ORGANIZACION DE COMPUTADOR II - FCEN
================================================================================
  definicion de estructuras para administrar tareas
*/
#include "defines.h"
#include "tss.h"
#include "gdt.h"
#include "mmu.h"

tss tarea_inicial;
tss tarea_idle;
tss tsss[CANT_TAREAS];

void setear_tss(tss* _tss, unsigned int _cr3, unsigned int _eip, unsigned int _pila, unsigned int _pila0,unsigned int D_SEGX, unsigned int C_SEGX)
{
	_pila += (unsigned int) 0x1000;		// Porque crece al reves, y primero se decrementa(sumar) y despues se escribe
	_pila0 += (unsigned int) 0x1000;		// Porque crece al reves, y primero se decrementa(sumar) y despues se escribe
	
	_tss->ptl = 0;
	_tss->unused0 = 0;
	_tss->esp0 = _pila0;				// Pila de nivel 0
	_tss->ss0 = 0;
	_tss->unused1 = 0;
	_tss->esp1 = 0;
	_tss->ss1 = 0;
	_tss->unused2 = 0;
	_tss->esp2 = 0;
	_tss->ss2 = 0;
	_tss->unused3 = 0;
	_tss->cr3 = _cr3;				// CR3
	_tss->eip = _eip;				// EIP
	_tss->eflags = 0x00000202;		// EFLAGS Habilitadas la interrupciones
	_tss->eax = 0;
	_tss->ecx = 0;
	_tss->edx = 0;
	_tss->ebx = 0;
	_tss->esp = _pila;				// Pila
	_tss->ebp = _pila;				// Pila
	_tss->esi = 0;
	_tss->edi = 0;
	_tss->es = D_SEGX;			
	_tss->unused4 = 0;
	_tss->cs = C_SEGX;			
	_tss->unused5 = 0;
	_tss->ss = D_SEGX;			
	_tss->unused6 = 0;
	_tss->ds = D_SEGX;				
	_tss->unused7 = 0;
	_tss->fs = D_SEGX;				
	_tss->unused8 = 0;
	_tss->gs = D_SEGX;				
	_tss->unused9 = 0;
	_tss->ldt = 0;
	_tss->unused10 = 0;
	_tss->dtrap = 0;
	_tss->iomap = (unsigned short) 0xFFFF;	// Mapa propuesto por la catedra (diapo 20_tareas_basico)
}

void cargar_tareas(tss* array_tareas) {
	unsigned int tarea;
	unsigned int indiceGDT = 3; //Empezamos a cargar esde la posicion 3 de la GDT
	
	//Vamos a cargar las 5 tareas	
	for (tarea = 1; tarea <= CANT_TAREAS; tarea++)
	{
		unsigned int offset_tarea = TAMANO_PAGINA*(tarea-1);
		
		unsigned int cr3Tarea = PDT1 + offset_tarea;
		unsigned int taskTarea = TASK1 + offset_tarea;
		unsigned int pilaTarea = TASK_STACK; //direccion virtual de la pila de nivel 3 (misma para todas las tareas)
		unsigned int pilaTarea0 = STT1 + offset_tarea; //Sumamo 0x1000 porque la pila se recorre al reves
		tss* comienzoTarea = array_tareas+(tarea-1);		
						
		//Cargamos la tarea en la GDT
		setear_descriptor_tss_GDT(indiceGDT, comienzoTarea, 3); //Ponemos nivel 3 para las tareas
				
		//Seteamos el tss de la tarea
		setear_tss(comienzoTarea, cr3Tarea, taskTarea, pilaTarea, pilaTarea0, D_SEG_N3, C_SEG_N3);
		
		//Mapea la pagina de la pila y la pagina el codigo 
		inicializar_dir_tarea(tarea);
		
		indiceGDT++;
	}
}

void cargarInicial(tss* inicial){
	//Cargamos la tarea inicial en el indice 1 del GDT
	setear_descriptor_tss_GDT(1,inicial,0); //Ponemos Nivel 0 para la tarea inicial  
}


void cargarIdle(unsigned int _cr3, tss* idle){
	setear_descriptor_tss_GDT(2,idle,0); //Cargamos la tarea idle en el indice 2 del GDT con Nivel 0
	
	//Cargamos el tss de la tarea IDLE
	setear_tss(idle,_cr3,TASKIDLE,STTI,STTI,D_SEG_N0,C_SEG_N0);
	//void setear_tss(tss* _tss, unsigned int _cr3, unsigned int _eip, unsigned int _pila, unsigned int _pila0, unsigned int D_SEGX, unsigned int C_SEGX)
	
	//Hacemos el identity mapping de lo 2MB
	//mapear_identity(_cr3);  ESTO YA ESTA HECHO PORQUE EL KERNEL ESTA IDENTITY MAPPING
	
	//Hacemos identity mapping con direccion Virtual: 003A0000 y direccion Fisica: 00010000 y CR3 del kernel
	mapear_pagina(TASK_CODE,_cr3,TASKIDLE,0x3);
	
	//Mapeamos la pila identity mapping 
	mapear_pagina(STTI,_cr3,STTI,0x3);
}
